package com.lhj.bootdemo.leecode;

import java.util.HashMap;

/**
 * @author lhj
 * @version 1.0
 * @date 2022/4/24 9:28 下午
 * @description:场景描述：由于公司需要频繁调用用户信息，每次都需要查询数据库， 现要求使用hashMap做一个缓存，缓存不能无限大，需要删除掉最近最少使用数据
 */

public class LruCache {

    public Node head;
    public Node tail;
    //缓存存储上线
    public int limit;
    public int size;
    public HashMap<Integer, Node> cache;

    public LruCache(int limit) {
        this.size = 0;
        this.limit = limit;
        cache = new HashMap<>();
        head = new Node();
        tail = new Node();
        head.next = tail;
        tail.prev = head;
    }

    /**
     * 添加
     *
     * @param key
     * @param value
     */
    public void put(int key, int value) {
        Node node = cache.get(key);
        if (null == node) {
            Node node1 = new Node(key, value);
            if (cache.size() == limit) {
                Node end = removeTail();
                cache.remove(end.getKey());
            }
            cache.put(key, node1);
            add2First(node1);
            return;
        }
        /**
         * 修改
         */
        node.setValue(value);
        move2First(node);
    }

    private void move2First(Node node) {
        removeNode(node);
        add2First(node);
    }

    private void add2First(Node node) {
        node.prev = head;
        node.next =  head.next;
        head.next.prev = node;
        head.next = node;
    }

    private Node removeTail() {
        Node prev = tail.prev;
        removeNode(prev);
        return prev;
    }

    private void removeNode(Node node) {
        node.prev.next = node.next.prev;
        node.next.prev = node.prev;
        node.prev = null;
        node.next = null;
    }

    /**
     * 获取
     *
     * @param key
     * @return
     */
    public int get(int key) {

        Node node = cache.get(key);
        if (null == node) {
            return -1;
        }
        //如果存在
        move2First(node);
        int value = node.getValue();
        return value;
    }


    /**
     * 双向链表
     */
    class Node {
        int key;
        int value;

        public Node(int key, int value) {
            this.key = key;
            this.value = value;
        }

        public Node() {
        }

        Node prev;
        Node next;

        public int getKey() {
            return key;
        }

        public void setKey(int key) {
            this.key = key;
        }

        public int getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }
    }


    public static void main(String[] args) {
        LruCache lruCache = new LruCache(3);

        lruCache.put(1,1);
        lruCache.put(2,2);
        lruCache.put(3,3);
        lruCache.put(4,4);

        lruCache.get(3);

        System.out.println(lruCache);
    }
}
